Copyright: Help text copyright 1995 by David A. Price


Index
Contents

Defining a new component

Opening a component definition file

Summary of advanced features

Menus

Component navigator

Main page

Properties page

Methods page

Events page

Variables page

Code editor

How do I

. . . install my new component onto the Delphi palette?

. . . change the palette bitmap of my new component?

. . . set the default value of an inherited property or hide the property?

. . . add properties with new enumerated types?

. . . publish a set property with more than 16 elements?

. . . add properties of object types?

. . . add properties that reference other components?

. . . create a component that wraps around a Delphi form?

. . . create a component with multiple sub-components?

. . . publish properties and events of sub-components?

. . . register a custom property editor?

. . . generate code for a custom property editor?

. . . make a component data-aware?

. . . work with multiple components at a time?

Sample files


Main page
Component navigator (Main page)

See also:  Menus

The Main page of the component navigator lets you review and edit general settings for the component.

The Code button on this page lets you edit the global declarations (normally just constant and type declarations) for your component's unit.  When you click the button, the current declarations, if any, will appear in an editor window.

Parent class name is the component's parent class.  This field is rarely changed after the component definition is created, but if you need to change it, press the New parent button and you will see the Select parent class dialog with an outline of the Delphi Visual Component Library, from which you can select a new parent class.

New class name is the name of the class for your new component.  It must be a valid Pascal identifier and, by convention, it begins with a "T".

New unit name is the name of the Pascal unit for your component, as well as the unit's Pascal code file.   It can be up to 8 characters long.

Description is a short description (up to 65 characters) of the component.  It will appear in the opening comment in the generated code.

Include units is the list of units for Component Create to place in the uses clause of the generated code.   To add a unit to the list, go to the Include units list box and press the INS key.  To remove a unit from the list, click on the unit name and then press the DEL key.

When you create a new component definition, Component Create will look up the unit for the parent class in its internal table of VCL classes and place the unit name in this field, along with a list of standard units.  If your own code needs other units, you can add those units here.

Default palette is the name of the component palette on which the component will appear by default within Delphi.

Copyright line is a field in which you can place a copyright notice (or a public domain notice) for your component.   It will appear in the opening comment in the generated code.


Properties page
Component navigator (Properties page)

See also:  Menus

The Properties page of the component navigator lets you review and edit settings and code for the component's properties.

The Add button on this page lets you add new properties to the component definition, or add properties from the parent class for which you want to set a default value.  (Your component will have all the properties of the parent class, whether or not they appear on this page.)

If the type you select for a new property is a standard Delphi object type, such as TFont or TStringList, the AutoInitialize method generated by Component Create will automatically allocate its storage variable, and the AutoDestroy method will automatically free it.   Also, your component will show the normal Delphi property editors for these types.

The Delete button lets you delete the property that is currently selected in the list box from the component definition.  You will be asked for confirmation.

The Code button lets you edit the read method and write method, if any, for the currently selected property. The code will appear in an editor window.  You can also double-click on a property in the list box to go to its code.

Name is the name of the currently selected property.

Description is a short description of the currently selected property.  If provided, it will appear in the comments in the generated code.

Data type is the Object Pascal data type of the currently selected property.  The auto-fill combo box will try to match the name of the data type as soon as you start typing it.

Default value, if supplied, is the default value of the currently selected property.  For example, if the property is of type Boolean, you could put True or False in this field to give the property that default value.

If the property is of a string type, this value should be enclosed by single quotes; if the data type is String, Component Create will add the quotes, if needed, when you leave this field.   (Otherwise, Component Create does not check to enforce compatibility between the default value and the data type.)

You do not need to set the property to the default value in your code.  The generated code will set the property to the default value in a method named AutoInitialize, which is called by the Create method.

Variable is the name of the storage variable, if any, for the property.  Your code can read or set the property value by reading or setting this variable.   If the variable needs to be declared, the generated code declares it for you.

Properties inherited from the parent class do not have storage variables in your new component class.  Instead, your code should read and set inherited properties directly.

The >>> button lets you select a custom property editor for the property, if desired.

The Inherited property check box indicates whether Component Create should treat the selected property as an inherited property from the parent class.

The Read-only property check box indicates whether the selected property is read-only; that is, whether an application can set the property's value or not.  Read-only properties do not appear in Delphi's Object Inspector at design time.

The Use read method check box indicates whether the selected property has a read method.  If it is checked, you can click the Code button to edit the property's read method.

The Use write method check box indicates whether the selected property has a write method.  If it is checked, you can click the Code button to edit the property's write method.

The Unpublish check box indicates whether the selected property should appear in the Object Inspector at design time.  Both new properties and inherited properties may be hidden with this option.

Component Create hides a new property by declaring it as "protected" rather than "published."  It safely hides an inherited property by declaring a new property of the same name as "protected" in the component.


Methods page
Component navigator (Methods page)

See also:  Menus

The Methods page of the component navigator lets you review and edit settings and code for the component's methods.

The Add button on this page lets you add new methods to the component definition, or add methods from the parent class that you want to override.  (Your component will inherit all the public and protected methods of the parent class, whether or not they appear on this page.)

The Delete button lets you delete the method that is currently selected in the list box from the component definition.  You will be asked for confirmation.

The Code button lets you edit the code for the currently selected method. The code will appear in an editor window.  You can also double-click on a method in the list box to go to its code.

The first combo box on the page indicates whether the currently selected method is a procedure, function, constructor, or destructor.

Header is the rest of the declaration header for the currently selected method.

Description is a short description of the currently selected method.  If provided, it will appear in the comments in the generated code.

A combo box lets you indicate whether the method (1) overrides an inherited method in the parent class, (2) is a new method that can be overridden in a descendant class, or (3) is a new method that cannot be overridden.  If the method can be overridden, you select between maximizing execution speed (in which case Component Create declares it as a virtual method) or minimizing code size (in which case Component Create declares it as a dynamic method).

Scope indicates whether Component Create should declare the method as public (available to an application containing the component and to any descendant classes of the component), protected (available to descendant classes of the component), or private (available only within the component itself).

For advanced component developers, Windows or VCL message to handle is the name of the Windows or VCL message, if any, that this method handles.  For example, if you want the method to be called in response to WM_SIZE messages, you would put WM_SIZE here.  See the Windows API help file for help on Windows notification messages and the VCL help file for information on VCL notification messages.


Events page
Component navigator (Events page)

See also:  Menus

The Events page of the component navigator lets you review and edit general settings and code for the component's events.

The Add button on this page lets you add new events to the component definition, or add events from the parent class that you want to publish or whose handler you want to override.

When the Show New Events button is down, the Add button lets you add new events.  When the Show Inherited Events button is down, the Add button lets you add inherited events to work with.  (Your component will have all the inherited events of the parent class, whether or not they appear on this page.)

The Delete button lets you delete the currently selected event from the component definition.  You will be asked for confirmation.

The Code button lets you edit the code for the currently selected event.  The code will appear in an editor window.  You can also double-click on an event in the list box to go to its code.

When the Show New Events button is down, the Code button lets you edit the method that will call the application's handler, if any, for the event.  When the Show Inherited Events button is down, the Code button lets you edit the method in your class that overrides the handler for the event in the parent class.

Event Name is the name of the currently selected event.

Description is a short description of the currently selected event.  If provided, it will appear in the comments in the generated code.

For inherited events, the Override handler in parent class check box indicates whether your component will include a method to override the event's handler in the parent class.  The Publish event check box indicates that the inherited event should be published, if it is not already.  Handler is the header declaration (not including the word "procedure") for the event's handler in the parent class.

New events added on this page are of type TNotifyEvent.


Variables page
Component navigator (Variables page)

See also:  Menus

The Variables page of the component navigator lets you review and edit settings for the component's variables.

The Add button on this page lets you add new variables to the component definition.  If the type you select for a new variable is a standard Delphi object type, such as TFont or TTimer, the AutoInitialize method generated by Component Create will automatically allocate it, and the AutoDestroy method will automatically free it.

The Delete button lets you delete the variable that is selected in the list box from the component definition.  You will be asked for confirmation.

If the currently selected variable is an object, the Code button lets you edit code to initialize its fields.  If the currently selected variable is a subcomponent, the Code button lets you edit code to initialize its properties.   (Otherwise, the Code button is disabled on this page.)

Name is the name of the currently selected variable.

Description is a short description of the currently selected variable.  If provided, it will appear in the comments in the generated code.

Data type is the Object Pascal data type of the currently selected variable.

Initial value, if supplied, is the initial value of the currently selected variable.

If the variable is of a string type, this value should be enclosed by single quotes; if the data type is String, Component Create will add the quotes, if needed, when you leave this field.   (Otherwise, Component Create does not check to enforce compatibility between the default value and the data type.)

The generated code will set the variable to the initial value in a method named AutoInitialize, which is called by the Create method.

Scope indicates whether Component Create should declare the variable as public (available to an application containing the component and to any descendant classes of the component), protected (available to descendant classes of the component), or private (available only within the component itself).

The Is object checkbox should be checked if the selected variable is a Delphi object (that is, a TObject descendant).  When you add a variable to the component definition, Component Create will check this box for you if it recognizes the type of the variable as an object type.  The code generated for the AutoInitialize method creates object variables, and the code generated for AutoDestroy frees them.

The Is subcomponent checkbox should be checked if the selected variable is a subcomponent (that is, its type is a component type).  When you add a variable to the component definition, Component Create will check this box for you if it recognizes the type of the variable as a VCL component type.  The code generated for the AutoInitialize method creates subcomponent variables and sets their Parent property; the code generated for AutoDestroy frees them.


Code editor window
Code editor

Component Create displays the code editor window when you click the Code button on a page of the component navigator.  On the Main page of the component navigator, it lets you edit the global declarations, if any.  On the other pages, it lets you edit the code that is associated with the currently selected property, method, event, or sub-component.

In addition to the normal keyboard shortcuts for text editing, the code editor recognizes ctrl-Y to delete the current line and shift-F1 for Delphi help.

If the cursor is on a word in the editor when you ask for Delphi help, you will get help on that topic, or Delphi's help system will display a list of relevant topics if there is more than one.  If the cursor is not on a word, you will get Delphi's help index.

A.  Code editor buttons

Press the OK button to leave the editor and keep all changes you made to the code.  Press the Cancel button to leave the editor and discard all changes you made to the code since you opened the window.

The View button lets you look at a file, such as a Pascal file, and copy all or part of it to the Windows clipboard.

The Paste button pastes the contents of the Windows clipboard, if any, into your code at the current cursor position.

The Restore default button replaces the current contents of the editor with Component Create's default version of the code you are editing.  For example, if you are editing a property's read method, clicking Restore default will replace your code with simple, but functional, read method code for the property.

B.  Code editor menus

The Edit menu of the code editor window includes Cut, Copy, Paste, Delete, Select all, and Undo items with the normal behavior.  It also includes an Undo all changes item, which resets the code back to the way it was when you entered the editor, and a Restore default code item, which has the same effect as the Restore default button.

The View menu of the code editor window includes Pascal file to let you select a Pascal file for viewing, and Form file to let you select a Delphi form (.DFM) file for viewing as source code.  The file you select is shown in the file viewer.

The Help menu of the code editor window is similar to that of the component navigator, with items for Help, Class help, VCL help, Delphi help, and About.


File viewer window
File viewer

The file viewer window appears when you select a file to view after pressing the View button or select the View | Pascal file or View | Form file menu items in the code editor window.  It also appears, at your option, after you generate component code or property editor code.  The viewer lets you look at, but not edit, a Pascal file, a form (*.DFM) file converted to text, and other text files.

In the 16-bit edition of Component Create, the file viewer shows only the first 32K or so of files that are larger than 32K.

To leave the file viewer window, press the OK button or the Alt-F4 key.


Select parent class dialog
Select parent class

The Select parent class dialog appears when you are creating a new component definition (by clicking the File | New component definition menu item) or when you are changing the component's parent class (by clicking the New parent button on the Main page of the component navigator).

The dialog has three views:  the VCL Outline View, the List View, and the Express View.  Use the view you prefer to select the parent class that your component will descend from.

To leave the dialog without selecting a parent class, press Cancel.

VCL Outline View

This view lets you pick from an outline.  It initially shows categories of components in the Delphi Visual Component Library.  Click the Expand outline button to expand this list into an outline view of the entire Delphi Visual Component Library.  Click the Shrink outline button to shrink the entire outline to its top level.  You can double-click on outline items to expand or shrink parts of the outline.

At the bottom level of the outline, click on the name of a parent class.  For example, if you want your new component to be derived from a Delphi button, you could select TButton or TBitBtn.  For more information about a parent class, press the Class Help button to get Delphi help on it (or a list of Delphi help topics on it).  The Class Help button is enabled only when a parent class name is selected in the outline.

If you want to create a component that wraps around a Delphi form (like a common dialog component), select the item "Wrapper for Delphi form" at the end of the outline.

When you've selected a parent class you want from the outline, press OK.  The OK button is enabled only when a parent class name is selected in the outline or when the "Wrapper for Delphi form" item is selected.

List View

This view lets you pick the parent class from a list of component classes or key in a name.  The auto-fill combo box will try to match the name of the class you want as you start typing.

If the class you select is a Delphi VCL component, you can press the Class Help button to get Delphi help on it.

If you want your component to descend from a component that is not in the Delphi VCL (such as a third-party component), you should use this view to enter its name.

If you select a non-VCL component, you will then be asked to give some information about that class:  the name of its closest ancestor class in the Delphi VCL (if you know it) and the name of the unit containing it.  After you have entered this information once for a parent class, Component Create will register it in its INI file for future use.

When you've selected a parent class you want, press the OK button.

Express View

This view, which is geared for novice users, lets you pick the parent class from a short list of component classes.

You can press the Class Help button to get Delphi help on the parent class you have picked.

When you've selected a parent class you want, press the OK button.


Add

The Add dialog appears when you click the Add button in the component navigator to add a property, method, event, variable, or unit name.

When adding a property or variable, enter its name into the edit box.  Enter or select its data type in the combo box; if you key in the data type, the auto-fill combo box will attempt to match its name as soon as you start.

When adding a method, select from the combo box to indicate whether it is a procedure, function, constructor, or destructor.  The rest of the method's header declaration should go in the edit box.

When adding an event or unit name, enter its name into the edit box.

Press OK when you are done, or Cancel if you have decided not to add the item.


Save component definition
File | Save component definition

If you have a component definition open, the Save component definition item on the File menu saves the component definition in a component definition (.CD) file.  If the component definition is a new one that has not already been saved, you will be asked for its file name.

If you have already saved the component definition to this file, the old version will be backed up to a file with the same name and a .BAK extension.


Save as
File | Save as

If you have a component definition open, the Save as item on the File menu saves the component definition in a component definition (.CD) file with the name that you specify.

If you have already saved the component definition to this file, the old version will be backed up to a file with the same name and a .BAK extension.


Print component interface
File | Print component interface

If you have a component definition open, the Print component interface item on the File menu prints the interface part of the class for your component.  It will include an opening comment with the time and date you generated the header to be printed.


Printer setup
File | Printer setup

The Printer setup item on the File menu lets you use the standard Windows printer setup dialog to choose your printer settings.


Exit Component Create
File | Exit Component Create

The Exit Component Create item on the File menu will ask whether you wish to save the component definition (if one is open), will save it if you so request, and will then exit Component Create.


Go to Main page
Page | Main

If you have a component definition open, the Main item on the Page menu will take you to the Main page.

Its effect is the same as clicking on the tab for that page.


Go to Properties page
Page | Properties

If you have a component definition open, the Properties item on the Page menu will take you to the Properties page.

Its effect is the same as clicking on the tab for that page.


Go to Methods page
Page | Methods

If you have a component definition open, the Methods item on the Page menu will take you to the Methods page.

Its effect is the same as clicking on the tab for that page.


Go to Events page
Page | Events

If you have a component definition open, the Events item on the Page menu will take you to the Events page.

Its effect is the same as clicking on the tab for that page.


Go to Variables page
Page | Variables

If you have a component definition open, the Variables item on the Page menu will take you to the Variables page.

Its effect is the same as clicking on the tab for that page.


Generate component code
Generate | Component code

If you have a component definition open, the Component code item on the Generate menu will generate a Pascal file containing a unit for your component.  You can then go to Delphi and install the component on Delphi's component palette, if you wish.


Help contents
Help | Help contents

The Help contents item, provided on the Help menus of the main window and the code editor window, displays the contents page of the Component Create help file.


Class help
Help | Class help

The Class help item, provided on the Help menus of the main window and the code editor window, displays the Delphi help for your component's parent class.

If more than one Delphi help topic exists for the parent class, you will be given a topic list from which you can choose.


VCL help
Help | VCL help

The VCL help item, provided on the Help menus of the main window and the code editor window, displays a list of Delphi help topics on the Visual Component Library from which you can choose to see Delphi help.


Delphi help
Help | Delphi help

The Delphi help item, provided on the Help menus of the main window and the code editor window, provides a quick link to the Delphi help system.

When selected from the main window, it displays the topic index for Delphi's help system.

Within the code editor, selecting Delphi help when the cursor is on a word will bring up the Delphi help topic, if any, for that word (or a list of relevant Delphi help topics if there is more than one).  The keyboard shortcut for Delphi help in the code editor is shift-F1.


About box
Help | About

The About item, provided on the Help menus of the main window and the code editor window, displays an About box containing copyright and other information about Component Create.


Read methods and write methods

Check boxes on the Properties page of the component navigator let you determine whether a property has a read method, a write method, both, or neither.

A property's read method is a function that will be called to determine the property's value whenever an application reads the property.  If a property does not have a read method, then the property's value is just the current value of its storage variable.

Read methods let you create properties that always track some condition, such as the time of day or the number of records selected in the component's latest database search.

A property's write method is a procedure that will be called to set the property's value whenever an application sets the property.  At that time, the write method can also perform any other necessary updating of the component.  If a property does not have a write method, then setting the property's value just sets the value of its storage variable.

Write methods let you create properties that have immediate effects whenever they are changed.  For example, a property with a write method can control the appearance of a visual component dynamically, by calling the component's Paint method (if its parent class has one) to force the component to be re-drawn right away when the property's value changes.


Generate palette bitmap
Generate | Palette bitmap

The Palette bitmap item on the Generate menu lets you create a custom bitmap for your component on Delphi's component palette.

By default, a component's bitmap is generally the same as that of its parent class.  To change your component's bitmap, use this menu item to create a .DCR (Dynamic Component Resource) file containing a simple bitmap.

When you use this menu item, Component Create will run the Borland Resource Compiler, which is a DOS-based application.  Under Windows 95, when the compiler finishes, you will see a prompt in the compiler's DOS window to press Ctrl-C to continue.

You can then edit the bitmap in the .DCR file with the Image Editor.  In Delphi, select Image Editor from the Tools menu.  There, click File | Open and select the .DCR file.

The .DCR file generated by Component Create follows Delphi's requirements for a palette bitmap: The file contains a bitmap of 24 x 24 pixels with the same ID as the name of your new component class.  By convention, the ID is all UPPER CASE.

When Component Create is set up to work with Delphi 1.0, it generates 16-bit resource files; when set up to work with Delphi 2.0, it generates 32-bit resource files.

By default, Component Create saves the .DCR file in the same directory and with the same name it would use for the Pascal source file.  (The file name is based on the unit name you specified on the Main page of the component navigator.)   The .DCR file should be in the same directory as the compiled unit because Delphi looks there for the file when it installs the component and places its bitmap on the palette.

Thus, if you have created a component with a class name of TSuperMemo, and a Pascal file name of Memoctrl.pas, Component Create would generate a bitmap with an ID of TSUPERMEMO and save it in Memoctrl.dcr.

Working from standard VCL bitmaps

To use the bitmap of an existing Delphi component as the starting point for your own bitmap, go to the Image Editor and locate the bitmap you want to work with in one of the .DCR files in the Delphi "Lib" directory.  Most components have their bitmaps in Lib\Stdreg.dcr.

Next, in the image editor, use the Edit | Select all menu item, then the Edit | Copy menu item, to copy the bitmap you want to the clipboard.  Finally, open the .DCR file generated by Component Create and use the Edit | Paste command to paste your desired bitmap in place of the simple one already there.  You can now edit the standard bitmap further to customize it for your component.


Creating a component definition
Creating a component definition (overview)

To begin creating a new component, click the New component definition item on Component Create's File menu.

1.  Select the parent class

Next you'll see a dialog showing a list of the types of components you can build.  This is the Select parent class dialog.

On the VCL Outline View page, you can click the Expand outline button in the dialog to expand this list into an outline view of the entire Delphi Visual Component Library.  You can double-click on outline items to expand or shrink parts of the outline.

At the bottom level of the outline, click on a parent class for your new component.  For example, if you want your new component to be derived from a Delphi button, you could select TButton or TBitBtn.  For more information about a parent class, press the Class Help button to get Delphi help on it (or a list of Delphi help topics on it).  When you've selected the parent class you want, press OK.

On the List View page, you can select the parent class from a list or type it in yourself.  Use this view if you want to use a third-party component as the parent class.

On the Express View page, you can select from a short list of parent classes.  This view is geared for novices.

2.  Create the component definition

Next you'll see a tabbed notebook that lets you browse and modify the component definition for your new component.  This is the component navigator.  General settings for the component (such as its parent class and unit name) are on the Main page of the navigator.  Properties are listed on the Properties page.  Methods of the class (its procedures, functions, constructor, and destructor) are on the Methods page.  Inherited events and newly-defined events are on the Events page.  Variables are on the Variables page.

Your component definition will begin with some methods and events appropriate to the parent class.  The navigator will not show all of the properties, methods, and events of the parent class, but you can add any of the other inherited properties, methods, and events that you want to work with.  You can also add new properties, methods, events, and variables.

To add a property, method, event, or variable to the component, go to the corresponding notebook page and click the Add button.

To edit a property, method, event, or variable, click its entry on the list box on its page and change the appropriate field on the bottom half of the page.  To attach code to an item (e.g., a property's read or write method), select the item and click the Code button.  You'll see a code editor with default code displayed.  Edit the code and press OK to exit with your changes retained or Cancel to discard them.

To remove a property, method, event, or variable, click its entry on the appropriate page and then click the Delete button.  Component Create will ask you for confirmation.

3.  Save the component definition and generate code

You can save your component definition (including all code) to a Component Definition (.CD) file with the File | Save component definition menu item.  While you're working on the component definition, you can get help on the parent class with the Help | Class Help menu item.  You can print the interface to your new class with the File | Print component interface menu item.  Finally, you can generate an Object Pascal unit for the component with the Generate | Component code menu item.  Later, if you wish, you can alter the component definition by opening its .CD file.


Installing a component
Installing a component onto the palette

After you've generated code for your new component with the Generate | Component code  menu item in Component Create, you can add the component to the Delphi component palette by switching to Delphi and selecting the Install Components command on the Options menu (in Delphi 1.0) or the Install command on the Component menu (in Delphi 2.0).

Press Add, then Browse, and select the Pascal file that Component Create generated. Press OK.  Delphi will compile the unit for your component and put it on the palette you selected (on the Main page of the component navigator in Component Create).

If Delphi reports a compiling error, switch back to this program, correct the error, and re-generate the component code.

To test your new component, create a new form in Delphi and drop your new component onto it.


Properties of set types
Publishing set properties

In Delphi, you can specify a set type as the data type of a published property, but only if the set type has 16 or fewer elements.

For example, if MyType is an enumerated type of 20 elements. you cannot give your component a published property of type set of MyType.

If you want your component to have a property that represents a set type with more than sixteen elements, you could instead make the property of type String, and give it read and write methods that internally convert the property's string value into a set.  Alternatively, you could publish the elements of the set separately as properties of type Boolean.


Components with sub-components

You can use Component Create to produce a Delphi container component (that is, a component enclosing multiple sub-components, such as a memo field and two buttons).  If you wish, you can lay out a panel visually in Delphi and then use Component Create to convert the panel into a new component.

To produce a container component, follow these steps:

1.  Select a container as the parent class

Click the New component definition item on Component Create's File menu.

Next, in the Select parent class dialog that appears, go to the Express View page and select "Multiple-Component Container Imported From A Form."  Press the OK button.

Or, on the VCL Outline View page, double-click on the outline item "Container for multiple components."  Select a container class, preferably either TPanel (if you want the developer to be able to set the properties of the panel) or TCustomPanel (if you want to hide some of the panel's properties).

2.  Import the container from a Delphi form

You will then be asked whether you want to import the container from an existing form (.DFM) file.  Select a .DFM file containing a panel (or group box) that you have laid out with the desired sub-components.

If the .DFM file contains more than one panel, you will be asked to select the one to import.  (If the .DFM file does not have any container components, you will get an error message.)

As Component Create reads the panel, it will ask whether you want a sub-component's OnClick or OnChange events or both (as appropriate) to be published in your new component, so that a developer can use the Delphi Object Inspector to add handlers to respond to these events.

After Component Create finishes importing the panel, you will see the component navigator with a complete component definition for your container component.

3.  View or edit initial property values for the sub-components

For each sub-component in the original panel, there is now a corresponding variable of the same name in the component definition.  To view or edit the code that has been created for initializing a sub-component's properties, go to the Variables page, select the variable, and click the Code button (or double-click the variable name in the list box).  In the code editor, you will see a Pascal "with" statement followed by assignments that will give the properties of the sub-component (such as Top, Left, Caption, etc.) the proper initial values.   You may edit these assignments or add to them.

4.  Respond to events in the sub-components

When Component Create imports a panel, it generates methods as appropriate to handle OnClick, OnChange, and OnKeypress events of the sub-components.  For example, if a button named Button1 was on the panel, your component definition will include a method named DoButton1Click, which will be called whenever Button1 is clicked.  Go to the Methods page and add code to these methods if you want your component to respond to these events.

The events that you chose to publish when you imported the form will be listed on the Events page.  Press the Show new events button on that page to see the list.

5.  Add properties that link with selected properties of the sub-components

You can add properties to the component definition that bring properties of sub-components to the surface.  Reading from or writing to that property of the container will then access the property of the sub-component.  For example, you might want to add a property named MemoLines that links with the Lines property of a TMemo in your container.  When you add a property to a container component, you will be asked whether you want to link it to a sub-component property, and if so, which one.

6.  Handle resizing of the component, if desired

If you want your container component to adjust the size or position of its sub-components when it is resized, you should override the component's OnResize event handler.  To do so, go to the Events page.  Make sure inherited events are showing (in other words, the Show Inherited Events button should be down).

Select the OnResize event from the list box.  Click the Override handler in parent class check box.  Then click the the Code button to go to the code for the event, where you can set the properties of the sub-components in response to resizing events.

7.  Add sub-components manually, if desired

Besides importing sub-components from a form file, you can add sub-components manually.  When the component navigator appears, go to the Variables page and click the Add button to add a new variable.   Give the variable the class type of the sub-component you want (for example, TButton).  The Is object and Is subcomponent check boxes should be checked, so that the AutoInitialize method generated by Component Create will create the variable with your new container as its parent.  Select "Private" for the variable's scope.  Click the Code button to set initial values of the sub-component's properties.

8.  Make the panel data-aware, if desired

If you want the panel to be data-aware, use the Edit | Add data link menu item to add one or more read-only or read-write data links to the panel.  Then edit the methods generated by that menu item to update the relevant sub-components (or update the data source, if appropriate).  See the help on Edit | Add data link for more details.

The sub-components on the panel should not be data-aware components.  For instance, you should use a TEdit on the panel rather than a TDBEdit.

9.  Panels within panels are not imported

The container you import should not have containers within it.  When you import a container, any containers within it are not included in the new component definition.


Opening a component definition file
Opening a component definition file (overview)

To browse or change a component definition that was previously saved in Component Create as a component definition (.CD) file, click the Open component definition menu item on the File menu.  Component Create comes with a number of sample .CD files.

Next, you'll see a tabbed notebook that lets you browse and modify the component definition.  This is the component navigator.  General settings for the component (such as its parent class and unit name) are on the Main page of the navigator.  Properties are listed on the Properties page.  Methods of the class (its procedures, functions, constructor, and destructor) are on the Methods page.  Inherited events and newly-defined events are on the Events page.  Variables are on the Variables page.

To add a property, method, event, or variable to the component, go to the corresponding notebook page and click the Add button.

To edit a property, method, event, or variable, click its entry in the list box on its page and change the appropriate field on the bottom half of the page.  To attach code to an item (e.g., a property's read or write method), select the item and click the Code button.  You'll see a code editor with default code displayed.  Edit the code and press OK to exit with your changes retained or Cancel to discard them.

To remove a property, method, event, or variable, click its entry on the appropriate page and then click the Delete button.  Component Create will ask you for confirmation.

You can save your revised component definition (including all code) to a Component Definition (.CD) file with the File | Save component definition menu item.  While you're working on the component definition, you can get help on the parent class with the Help | Class Help menu item.  You can print the interface to your new class with the File | Print component interface menu item.  Finally, you can generate an Object Pascal unit for the component with the Generate | Code menu item.


Setting and hiding inherited properties

All of the properties of your component's parent class are inherited by your component.  After you have added an inherited property to the Properties page, you can set its default value or hide it.

A.  Setting default values

Your component definition can set a new default value for a property published by the parent class (assuming that the property is not a read-only property).  Just add the property to the component definition by pressing the Add button on the Properties page of the component navigator, check the Inherited property check box, and put the desired value in the Default value field.

B.  Hiding individual properties

Normally, any property that is published in your component's parent class will also be published by your component.  If it is a read-write property, it will therefore be accessible at design time in Delphi's Object Inspector when the component is selected on a form.

If you want to prevent the developer who is using your component in an application from seeing it in Delphi's Object Inspector at design time, select it on the Properties page and check the Unpublish check box.

In your code, you can still read and set the property's value.  Precede its name with the reserved word "inherited."  For example:

inherited Caption := 'Update';

if inherited MaxLength = 0 then . . .

C.  Hiding groups of properties

Some parent classes in the VCL have "custom" versions (actually ancestors)  that do not publish some of their properties.  For example, TEdit has a "custom" version named TCustomEdit.  If you use a "custom" version as the parent class, you can decide whether to publish these unpublished properties and make them accessible.

If you do not add an unpublished property to the component definition on the Properties page of the component navigator, it will remain unpublished in your component.  You can still assign it a value in your component's code.  (In this case, you do not use the word "inherited.")


Variables and properties of object types

When you are coding a Delphi component by hand, and one or more of its variables or properties is of an object type (such as TFont or TStringList), it is easy to make mistakes that lead to Windows general protection faults.  Component Create automates the creation, updating, and freeing of object properties.

Every component class generated by Component Create includes two procedures named AutoInitialize and AutoDestroy.  These procedures are generated by Component Create and should be called in the component's Create and Destroy methods respectively.  (Component Create's default code for the Create and Destroy methods does so.)

For each property or variable of a type that Component Create recognizes as a standard Delphi object type, such as TFont, TBitmap, TTimer, or TStringList, AutoInitialize creates it. The two exceptions to this rule are (1) a property inherited from the parent class, because the parent class will create it, and (2) a property of a component type, because it should be assigned the value of a compatible component that already exists.

AutoDestroy frees each object created in AutoInitialize.

Bear in mind that AutoInitialize and AutoDestroy only create and free an object.  Thus, simply adding a TFont property (for example) will not affect the behavior of your component.  For an object property to affect the behavior of your component, you need to add code to your component's methods to make that happen.  Normally, this means adding code to the property's write method and to the component's Paint method (if it has one).

If the component you are creating is a container (that is, if you have given it a parent class that is a container, such as TPanel), and if a variable you have added to the component is itself a component (such as TButton or TTable), then AutoInitialize not only creates the component, but also assigns the container as its Parent property.  This makes it easy to produce components with sub-components.

Besides creating objects, AutoInitialize also sets non-object properties and variables to their default or initial values, if any.


Publishing properties and events of sub-components

When you import a container component from a Delphi form, Component Create automatically publishes key events of the container so they are available to users of your component.  To publish sub-component properties, or to publish events that Component Create has not published for you, do the following steps.

A.  Publishing sub-component properties

Suppose you have imported a container component of type TPanel with various sub-components, including a TButton variable named Button1.  Suppose, also, that you want to publish the Caption property of sub-component Button1 so it can be set from the Object Inspector.

To do so, you would add a property to the container component definition.  Name it ButtonCaption, for example.  When you add the property, Component Create will ask whether it should link with a property of a sub-component.  If so, Component Create will display a dialog asking you to choose the name of the property and sub-component to link with.

Here, you would enter Caption for the property name and select Button1 as the sub-component.   Component Create would then add ButtonCaption to the component definition with read and write methods that connect the new property with the value of the sub-component's Caption property (Button1.Caption).  Any references to the container component's ButtonCaption property would read or write Button1.Caption.

B.  Manually adding methods to handle sub-component events

If you did not ask Component Create to publish the OnClick event of Button1 when the component was imported, here are the steps to make this container component's code respond to an OnClick event in the sub-component Button1:

1.  Add a method that is type-compatible with OnClick, which is of type TNotifyEvent.  This means adding a procedure with one argument named Sender of type TObject.  Thus:

procedure DoButtonClick(Sender : TObject)

2.  Put the functional code in that method to define how the component will respond when Button1 is clicked.

3.  In the container component's Create method, assign this method to the sub-component's OnClick property:

Button1.OnClick := DoButtonClick;

Now DoButtonClick will be called whenever Button1 is clicked.

C.  Manually publishing sub-component events

To publish the OnClick event for Button1, so that a form with the container on it can respond when Button1 is clicked, do steps 1-3 above.  Then do the following:

4.  Add a new event to the container.  Call it, say, OnButtonClick.  To add it, go to the Events page of the component navigator, press the Show New Events button, and press the Add button.

5.  This will also create a new method named ButtonClick.   Calling that method triggers the OnButtonClick event.  Add a call to ButtonClick in the code for DoButtonClick.

Now OnButtonClick will appear in the Object Inspector with the other events for the container when the container is selected on a form.


Cut
Edit | Cut

The Cut item on the Edit menu will cut any selected text on the current page of the component navigator and paste it to the Windows clipboard.


Copy
Edit | Copy

The Copy item on the Edit menu will copy any selected text on the current page of the component navigator and paste it to the Windows clipboard.


Paste
Edit | Paste

If the active control on the component navigator is a text control, the Paste item on the Edit menu will paste the contents of the Windows clipboard into that control.

If the active control is one that accepts only a single line of text, then the Windows clipboard contents will be pasted only up to the first return character (i.e., from the ENTER key).


Source directory
Options | Source directory

The Source directory item on the Options menu allows you to set the default directory for Component Create to use when you open a component definition (.CD) file.  When you change the directory, Component Create updates its INI file.


Code directory
Options | Code directory

The Code directory item on the Options menu allows you to set the default directory for Component Create to use when you generate Pascal code with the Generate | Component code command.  When you change the directory, Component Create updates its INI file.


INI file

Component Create looks for its INI file, COMPCREA.INI, in the same directory as its executable file, COMPCREA.EXE.  If Component Create cannot find its INI file, or if an entry is not present in the file, it uses default settings instead.

[Directories] section

The [Directories] section of the INI file contains information about default directories for files.  The directories can be changed by the user within Component Create using the Options menu.

PascalCode=

The PascalCode item is the path name of the directory that Component Create should use by default when writing a Pascal code file.  Set by Options|Code directory.

Definitions=

The Definitions item is the path name of the directory that Component Create should use by default when the user is opening a Component Definition (.CD) file.  Set by Options|Source directory.

[HelpFiles] section

The [HelpFiles] section of the INI file contains the path names of the Delphi 1.0 help files.  These entries are not used when Component Create is set up to work with 32-bit Delphi.

DelphiHelp=

The DelphiHelp item is the path name of the main Delphi 1.0 help file.

CWGHelp=

The CWGHelp item is the path name of the Delphi 1.0 Component Writer's Guide help file.

[Resources] section

Compiler16=

The Compiler16 item in the [Resources] section is the path name of the 16-bit version of the Borland Resource Compiler (BRCC.EXE).  Set by Options|Resource compiler path when Component Create is set up to work with Delphi 1.0.

Compiler32=

The Compiler32 item in the [Resources] section is the path name of the 32-bit version of the Borland Resource Compiler (BRCC32.EXE).  Set by Options|Resource compiler path when Component Create is set up to work with 32-bit Delphi.

[Other] section

FullComments=

The FullComments item in the [Other] section is 1 for detailed comments in the generated code, 0 for normal comments in the generated code.  Set by Options|Commenting level.

UsingDelphi16=

The UsingDelphi16 item in the [Other] section is 1 for using Component Create with 16-bit Delphi, 0 for using it with 32-bit Delphi.  Set by Options|Delphi version.

[Class. . . .] sections

A new parent class is registered when the user picks a parent class that is not recognized by Component Create (such as a third-party component).  A section is added to the INI file for every new parent class that the user registers.  The sections are of the form:

[Class.TSomeClassName]

Ancestor=TSomeAncestorName

Unit=SomeUnit

The ancestor name is the Delphi VCL ancestor, if any, that the user provided for the new parent class.  The unit name is the unit containing the new parent class.


Wrapping forms
Wrapping a component around a form

A wrapper component is one that wraps around a Delphi form (like the common dialog components provided with Delphi, but based on a form designed by you).

A wrapper component is distinct from a container component, such as a TPanel.  A wrapper component incorporates an entire form, which is displayed only when its Execute method is called; a container component incorporates multiple components, which are displayed whenever the container is present on a form.

To create a wrapper component, click the New component definition item on the File menu.  On the Select parent class dialog that appears, go to the Express View page and select "Wrapper Around A Form" at the bottom of the list.  Or, on the VCL Outline View page, select the item "Wrapper for Delphi form" at the bottom of the outline.

You will be asked to select the .DFM file for the Delphi form that you want the component to wrap around.  After you do so, Component Create will read the class name from the form file and create the component definition.

The component definition begins with properties that expose the Caption, HelpContext, and ModalResult properties of the form.  The component's Execute method displays the form.

Transferring data between the form and your component

You can expose other form properties in a wrapper component.  If you want the contents of a control on the form to be accessible to the application, you create properties in your "wrapper" component that correspond to the data in the control, such as the text in an edit box, the boolean value corresponding to the state of a check box, the integer value in a TSpinEdit control, or the integer value corresponding to which radio button of a TRadioGroup is selected.

For each property of the form that you want your component to publish, do the following two steps:

(1) Add a property of the same data type to the component definition on the Properties page.  Supply a default value for the property.

(2) Go to the code for the component's Execute method on the Methods page.  In the places indicated by the default code, perform assignments between the form's property and the value of the wrapper component's corresponding property.


Advanced Features
Summary of advanced features

The following are some of the advanced features of Component Create.  Click on the highlighted terms to get more information about the ones you want to learn about.

Importing container components from form files.  Creating container components with multiple sub-components is as easy as laying out a panel on a form in Delphi, saving the form, and pointing Component Create at it.

Components that wrap around forms.  It's easy to create a component that encapsulates a Delphi form.  Just select the "Wrapper for Delphi form" option in the Select parent class dialog.

Hidden properties.  You can make properties (including inherited properties) invisible in Delphi's Object Inspector.  Just check the Unpublished check box on the Properties page.

Generating palette bitmaps.  Click the Palette bitmap item on the Generate menu to get a custom bitmap for your component.  Component Create generates a resource file ready for you to edit in the Image Editor.  When you install the component in Delphi, the bitmap will be on the palette.

Easier development of components with object variables.  When you add a variable of an object type to a component, you can set the initial values of its fields in a snap.  Just select the variable on the Variables page and click the Code button.

Code editor.  Component Create's internal code editor provides undo and smart tabbing.  And you can get context-sensitive Delphi help by placing the cursor on a Delphi keyword and pressing shift-F1.

Viewing form (*.dfm) files.  The file viewer lets you see Delphi form files converted into text.  Just select the View | Form menu item in the code editor, and you'll see a list of the form's properties and the properties of its components.

Data-aware components.  It takes just a few mouse clicks to add a data link that makes your component data-aware.

Property editor registration.  Press the >>> button on the Properties page to select a custom property editor for the selected property.

Property editor generation.  To develop custom property editors that integrate into the Delphi Object Inspector, select the Generate | Property editors menu item.  It generates an Object Pascal unit file for some or all of the custom property editors you have requested in the component definition.  Choose from numerous property editor styles.

Improved support for grid and media player components.  OnDrawCell and OnDrawDataCell events appear, as appropriate, on the Events page for grid components.  This makes it easy to create grid components with custom cell drawing.  And when you descend from TMediaPlayer, you get a full set of its properties and events to work with.

Full control over the component's unit list.  If you wish, you can remove unneeded units from the list of standard Delphi units that Component Create places in the uses clause of the generated Pascal code.  Just go to the "Include units" list box on the Main page, click the unit name you want to remove, and press DEL.

Setting of default directories.  You can set the default directories that Component Create uses for reading and writing component definition (.CD) files and for writing Pascal code files.  Just select the Options | Source directory or Options | Code directory menu items.

Setting of commenting level.  You can choose between detailed commenting and normal commenting in your generated Pascal code.  Just select the Options | Commenting level menu item.


Component navigator menu
Menus

File

New component definition

Open component definition

Save component definition

Save as

Print component interface

Printer setup

Exit Component Create

Edit

Cut

Copy

Paste

Add data link

Page

Main

Properties

Methods

Events

Variables

Generate

Component code

Property editors

Palette bitmap

Options

Source directory

Code directory

Commenting level

Resource compiler path

Delphi version

Help

Help contents

Class help

VCL help

Delphi help

About


Property editor options

The Property editor options dialog appears when you press the >>> button on the Properties page.

It allows you to determine how the property is edited at design time in the Object Inspector.  You decide whether the Object Inspector uses Delphi's default property editor for that data type, or a custom property editor.

If you want to use a custom property editor, you supply the name of the Object Pascal unit containing the editor and the class name of the editor itself.  For example, a custom property for TBitmap properties might be in a unit named PropEds and its class might be named TMyBitmapEditor.

If you want the property editor to apply to all properties of the same data type in your component, check the Apply to all properties of this type checkbox.

The property editor that you specify can be one that has been developed entirely outside Component Create, or one that you have developed with the aid of Component Create.  The Generate | Property editors menu option generates a property editor unit that you can customize.


Commenting level
Options | Commenting level

The Commenting level item on the component navigator's Options menu allows you to determine whether code is generated with detailed comments or normal comments.

Changing the commenting level affects only new code.  If you have already edited code for a property, method, or event, the commenting for that code will not be affected (unless you press the Restore default button in the code editor to re-generate the code).

When you change the commenting level, Component Create updates its INI file accordingly.


Generate property editors
Generate | Property editors

See also:

Property editor options

Custom property editor dialogs

If you have selected custom property editors for properties in the component definition, the Property editors item on the Generate menu writes an Object Pascal unit file of the property editors.   You can then edit this unit in Delphi, if you wish, to adapt it to the needs of your component.

If you have provided one unit name for all the custom property editors, then Component Create will generate that unit.  If you have provided different unit names, then you will be asked which unit you want generated.

For each custom property editor that is being generated, you will be asked what type of property editor you want.  Depending on the data type of the property, you will have one or more of the following choices:

Edit in dialog, view in Object Inspector.  Property is edited in a Delphi form that you specify.  Property value can be viewed, but not directly edited, in the Object Inspector.

Edit in dialog or Object Inspector.  Property is edited in a Delphi form that you specify.  Property value can also be edited directly in the Object Inspector.

Edit and view in dialog only.  Property is edited in a Delphi form that you specify.  Property value cannot be viewed or directly edited in the Object Inspector.

Drop-down list, view in Object Inspector.  Property value is selected from a drop-down list.  Property value can be viewed, but not directly edited, in the Object Inspector.

Drop-down list, edit in Object Inspector.  Property value is selected from a drop-down list.  Property value can also be edited directly in the Object Inspector.

Message box.  For Boolean properties only.  Displays a message box that indicates the current status of the property and asks whether to change it.

Message box with input line.  For string properties only.  Displays a message box on which the property value can be entered or edited.  Property value can also be edited directly in the Object Inspector.

File name dialog.  For string properties only.  Displays a Windows "file open" dialog.  Property value can also be edited directly in the Object Inspector.

Directory name dialog.  For string properties only.  Displays a dialog for navigating to and selecting a file directory.   Property value can also be edited directly in the Object Inspector.

Component drop-down list.  For component-type properties only.  Property value is selected from a drop-down list of the compatible components (i.e., same component class or a descendant class) on the form.  You can edit the generated property editor code so that components are included or excluded from the drop-down list depending on their property values,


Custom property editor dialogs

When you generate property editor code, you can request a property editor based on a form you have designed.  If you select one of the property editor types that uses a form, you will be asked to select the Delphi form file (*.dfm) for it to use.

The form's code should declare a public field named Value, with the same data type as the property, to serve as a transfer buffer.  At design time, the property editor code will assign Value the current value of the property before the form is activated.  Your form's OnActivate event handler should then set its visual components to display the property's value.

If the form closes with a ModalResult of mrOK, your form's code should update Value with the new property value.  The property editor code will then update the property accordingly.

The following sample forms and units, which you can incorporate into your own components, are provided to illustrate how to create a form for a custom property editor:

EDIT_INT (.DFM/.PAS):  Property editor dialog for integer types

EDIT_FLT (.DFM/.PAS):  Property editor dialog for floating-point types

EDIT_STR (.DFM/.PAS):  Property editor dialog for string types

EDIT_SL (.DFM/.PAS):  Property editor dialog for TStringList and TStrings types


Delphi version
Options | Delphi version

The Delphi version item on the Options menu allows you to determine whether Component Create is set up to work with 16-bit Delphi (Delphi 1.0) or 32-bit Delphi.

When Component Create is set up to work with Delphi 1.0, it will use the Delphi 1.0 help files when you ask for Delphi help, and it will generate 16-bit resource files when you generate palette bitmaps.  When Component Create is set up to work with 32-bit Delphi, it will use Delphi32 help files and generate 32-bit resource files.

The Delphi version selection does not affect the generated code.


Resource compiler path
Options | Resource compiler path

The Resource compiler path item on the Options menu allows you to change the path name used by Component Create for the Borland Resource Compiler.  The Resource Compiler is a utility included with Delphi.  Component Create runs the Resource Compiler to produce a .DCR file when you generate a palette bitmap.

You need to change this setting only if you have installed Delphi into directories other than the default ones.

Component Create uses two versions of the Resource Compiler, depending on whether you are generating 16-bit palette bitmaps (for Delphi 1.0) or 32-bit palette bitmaps.  When Component Create is set up to work with Delphi 1.0, it runs BRCC.EXE, and setting the Resource Compiler path sets the path name to use for that program.  When Component Create is set up to work with 32-bit Delphi, it runs BRCC32.EXE, and setting the Resource Compiler path sets the path name for that program.


Sample files

The following sample files are provided in your Component Create directory:

Basic component creation

clock.cd (TClockLabel):  Label that displays current date and time.  Illustrates updating of component with TTimer.

inifont.cd (TIniFont):  Maintains a font value in its Font property.  Links with the .INI file, if any, named in its IniFile property.

monthcmb.cd (TMonthCombo):  Combo box with list of months.  Illustrates setting fixed contents of a string list property within component, unpublishing inherited properties, using Loaded method to set property values that depend on other properties.

mygrid.cd (TMyGrid):  String grid with custom cell drawing.

obj_prop.cd (TObjectPropertyDemo):  Illustrates object-type properties and component-type properties (i.e., properties referencing another component).

progress.cd (TProgress):  Simple progress bar control.  Illustrates painting a component from scratch.

rtfopen.cd (TRtfOpen):  Dialog for opening an RTF file.  Illustrates descending from a common dialog component, unpublishing an inherited property (Options).

undomemo.cd (TUndoMemo):  TMemo control with undo.  Illustrates KeyPress handling.

Container component creation

ol_panel.cd (TOutlinePanel):  Outline plus Shrink and Expand buttons to control it.  Several sub-component properties and events are published.

ol.dfm:  Source file from which ol_panel.cd was imported.

Custom property editor registration and generation

propedit.cd (TPropEditDemo):  Component that registers property editors.

edit_int.dfm, edit_int.pas:  Sample property editor form for integer property.

edit_flt.dfm, edit_flt.pas:  Sample property editor form for floating-point property.

edit_str.dfm, edit_str.pas:  Sample property editor form for string property.

edit_sl.dfm, edit_sl.pas:  Sample property editor form for TStrings or TStringList property.

Data-aware component creation

dblabel.cd (TDbLabel): Data-aware label, similar to TDbText; illustrates read-only data link

multfld.cd (TMultiFieldLabel): Data-aware label with data links to two fields of a data source

dbunedit.cd (TDbUndoEdit):  Data-aware edit box with undo; illustrates read-write data link


Properties referencing components

To add a property that can reference another component on the current form (like the Datasource property in data-aware VCL components), just add a property of the component type that you want the property to reference.

For example, if you want a property named StatusLabel that can reference any TLabel on the form, go to the Properties page and add a property named StatusLabel of type TLabel.

At design time, the Delphi Object Inspector will allow the developer to select any label on the form as the value of StatusLabel.

Within your component code, if StatusLabel is not nil, then it is associated with a label.  You can update the caption of the label associated with StatusLabel like this:

if StatusLabel <> nil then

   StatusLabel.Caption := 'Working . . .';

When a component definition includes a component-type property, Component Create automatically generates a method named Notification that resets the property value back to nil if the associated component is deleted from the form.  This method prevents the GPF that could otherwise result.


Field collection components

The TRzBusinessComponent class, developed by Ray Konopka, is a parent class that lets you create field collection components, which are non-visual components that encapsulate information about a set of fields and business rules associated with them.  Field collection components let Delphi 1.0 developers accomplish some of the encapsulation that Delphi 2.0 developers can accomplish with data modules.

Field collection components create field components on the form.  The field components created by a field collection component are available to data-aware controls on the form.   A field collection component can incorporate business rules by defining calculated fields and methods for filling the calculated fields.

To produce field collection components in Component Create, follow these steps:

1.  Create the component definition

First, double-click "Field collection component" in the Select parent class dialog, select TRzBusinessComponent, and then press OK.

2.  Add field properties

Next, go to the Properties page of the component navigator and add field properties for each of the fields to be generated by your component.  For example, an employee number may be represented by a property named EmployeeNum of type TIntegerField.

(In the generated code, Component Create will declare field properties as "public" rather than "published" so that they will be available to other components on the form, but will not appear in the Object Inspector.)

3.  Create the data field sub-components

Go to the Methods page and select the CreateFields method that has been provided in the component definition.  Press the Code button to edit the method's code.

For each data field, initialize the variable for its field property within CreateFields with a call to the CreateField method (declared in TRzBusinessComponent).  To control the appearance of the field when displayed by data-aware components, you will also want to set the field's DisplayLabel property and perhaps others (such as Alignment).  For example, if EmployeeNum is to correspond to the dataset field "EmpNo", you might write:

FEmployeeNum := CreateField( 'EmpNo' ) as TIntegerField;

FEmployeeNum.DisplayLabel := 'Employee #';

4.  Create the calculated field sub-components, if any

For each calculated field, initialize the variable for its field property in CreateFields with a call to CreateCalcField instead of CreateField.  CreateCalcField takes three arguments, which are the name of the field, its class type (e.g., TStringField, TIntegerField), and its size.  For example:

FOvertimePay := CreateCalcField('OvertimePay', TFloatField, 0);

FOvertimePay.DisplayLabel := 'Overtime pay';

FOvertimePay.Currency := True;

The size argument is ignored unless the field is a TStringField, TBCDField, TBlobField, TBytesField, or TVarBytesField.  (Thus, it is given as 0 in the example above.)

5.  Add methods for determining calculated field values

On the methods page, add public-scope functions to determine the values of calculated fields.  At design time, the developer using the component can call these methods to fill the calculated fields in the OnCalcFields handler of the table.   For the OvertimePay calculated field declared above, a function named CalcOvertimePay might be declared in the field collection component as follows:

function TMyBizComponent.CalcOvertimePay : Double;

begin

     { Pay and OvertimeHours are TFloatFields.  The pay rate

     for overtime is the base hourly pay rate at time-and-a-half. }

     Result := Pay.Value * 1.5 * OvertimeHours.Value

end;

The developer using the component would double-click the OnCalcFields entry for the table in the Object Inspector and incorporate CalcOvertimePay like this:

procedure TMyForm.Table1CalcFields(DataSet: TDataSet);

begin

     Table1OvertimePay.Value := MyBizComponent1.CalcOvertimePay

end;

As the business rule for determining overtime pay evolved in the future, only the code for TMyBizComponent would need to be updated; the specifics of the rule are hidden from the code for the user interface and database access layers of the application.

6.  Add methods for validating input values

To provide validation rules in the component, add public-scope functions that can be called in the OnValidate handler of the field.  For example, if EmpNo must be a positive integer, the component could include a function named ValidateEmpNo that returns True if EmpNo.Value is positive:

function TMyBizComponent.ValidateEmpNo : Boolean;

begin

     { EmpNo must be positive }

     Result := EmpNo.Value > 0

end;

At design time, the developer would add code to the field's OnValidate handler to raise an exception if the validation method returns False.

It is also possible to set up the validation method so that its name can directly be assigned as the value of the OnValidate event of the field.  (One does so by writing the method as a procedure with one argument named Sender of type TField.)  This approach is not recommended, however, because the developer can inadvertently replace the assignment by adding an OnValidate handler at design time.

TRzBusinessComponent is declared in the RzBizCmp unit, which is included with Component Create courtesy of Ray Konopka.  His useful book, Developing Custom Delphi Components (Coriolis, 1996), documents the class in detail.


Add data link
Edit | Add data link

The Add data link item on the Edit menu adds a link between your component and a data source.  You add one or more data links to your component to make it data-aware.

Data link properties

When you select this menu item, you will first be asked whether you wish to add a data link that is read-only (for database browsing) or read-write (for database editing).  You will then choose the names for the data link object and for the data source and data field properties associated with the data link.  If the data link you are adding is the first one in the component, you will see "DataSource" and "DataField" supplied as the default property names.

Data link event handlers

You will also choose the names for the method or methods that will act as event handlers for the data link.  Default method names will be provided.  If a method does not already exist, Component Create will generate it.

If the data link is read-write, it will have event handling methods for OnDataChange, OnUpdateData, OnEditingChange, and OnActiveChange.  If the data link is read-only, it will have only an OnDataChange event handler.

These events are not events of your component, but events of the data link object that are handled within your component.  For example, when the data in a field changes, the data link object fires an OnDataChange event.  The method that you specify will be called in response to this event, where it presumably will change the appearance of your component (e.g., the Caption property of a label component).

After you add the data link, you make your component interact with it by adding code to the method or methods that the Edit | Add data link menu item generated.  Comments in the methods explain what to do depending on the nature of your component.

You can add multiple data links by using the Edit | Add data link menu item more than once.  A method can act as the event handler for more than one data link.

Data link methods

If you have added a read-write data link, you will also need to add references in your component to methods of the data link object.  Wherever your component code may change the property or properties that correspond to the data field (e.g., the Text property of a data-aware edit box), you need to call the data link's Edit method beforehand to put the data link into editing mode and call its Modified method afterward to signal a change.  For example, if the data link is named FDataLink, you would write:

FDataLink.Edit;

CodeToUpdateTheComponent;

FDataLink.Modified;

A data link object also has an UpdateRecord method that your component should call when it loses the focus (normally in its OnExit handler).

Data links are objects of type TFieldDataLink, which is declared by the Visual Component Library in Dbtables.pas.

For examples of code for data-aware components, see VCL source code file Dbctrls.pas and Component Create sample files Multfld.cd (label that links with multiple fields of a data source) and Dbunedit.cd (data-aware edit control with undo).

Data field property editors

Normally, Delphi's Object Inspector provides a drop-down field list only for data field properties named "DataField" associated with a data source property named "DataSource."  If the data field or data source property has another name, the developer must type the field name.  To allow the developer to see a drop-down list of fields in the Object Inspector for a data field property with another name, component writers developing components with multiple data links need to register a custom property editor for each such data field property.

To do so, select the data field property (whatever its name) on the Properties page and press the ">>>" button.  Enter a property editor unit and class name.  Then, generate the property editor unit with the Generate | Property editors menu item.  Select "Drop-down list of data field names" as the property editor type.

If your component's data source property has a name other than "DataSource," you will also need to edit the DataSourcePropName constant in the GetValues method of the generated property editor class.


New component definition
File | New component definition

The New component definition item on the File menu lets you create a new component definition.  After you click this menu item, you will see the Select parent class dialog, where you should select the component that your new component will descend from.

For more information on creating a new component, see the overview of creating a component definition.


Open component definition
File | Open component definition

The Open component definition item on the File menu lets you open a component definition file that has already been created and saved in Component Create.

After you click this menu item, you will see a dialog for selecting a component definition (.CD) file.  Once you select a file, you will be able to browse or modify the definition.

For more information on working with an existing component definition, see the overview of opening a component definition.


Register new parent class

The Register new parent class dialog appears when you select a parent class that is not part of the Delphi VCL (such as a third-party component) and that you have not previously registered.

The dialog asks for two items of information:  the closest ancestor of the parent class from the Delphi VCL and the unit where the parent class is located.

For example, if the parent class you have selected is a descendant of TCustomComboBox and is located in unit NewCombo, you should enter those names.

The closer the VCL ancestor that you provide, the better an initial component definition that Component Create can provide.

If you do not know any of the Delphi VCL ancestors of the parent class, but you know that it has mouse events (like OnClick and OnDblClick) and keyboard events (like OnKeyDown and OnKeyPress), use TCustomControl as the ancestor.  If you know that it has mouse events, but no keyboard events, use TGraphicControl as the ancestor.

If you still cannot name a Delphi VCL ancestor of the parent class, check the check box.  In that case, Component Create will give you a component definition without any inherited events set up on the Events page.  If you want your component to add its own handling of events that are handled by the parent class, you will need to go to the Events page and add them.

The information you provide will be stored in the Component Create INI file so that it does not need to be entered again.


Properties of enumerated types

To declare and publish a property of a new enumerated type, follow these steps:

Declare the type.  Go to the Main page of the component navigator and press the Code button.  The code editor will show the global declarations, if any, for the component.  There, add the declaration for the enumerated type.  For example:

type

Direction = (North, Northwest, West, Southwest,

South, Southeast, East, Northeast);

Add the property.  Then add the property or properties with this new type.  Go to the Properties page of the component navigator and press the Add button.

When the component is generated and installed onto the Delphi palette, the Delphi Object Inspector will show a drop-down list of the possible property values for all properties of that type.  (That is also how the Object Inspector handles predefined enumerated types, such as Boolean.)


Multiple instances of Component Create

You can work with more than one component definition at a time (for example, to copy code between component definitions) by running multiple instances of Component Create.

After starting one instance of Component Create, just start another in the normal way: by selecting it on the Tools menu in Delphi or by running it from the Windows Program Manager or File Manager.